#ifndef ZG_QUEUE_H
#define ZG_QUEUE_H

#include "deque"
#include "Event.h"
#include "Mutex.h"
#include "SharedPtr.h"
#include "memory"
using std::deque;
#define MAX_SIZE 2048
namespace zg_util{
    class QueueItem{
    public:
        QueueItem(){}
    };
    template <typename T>
    class QueueItemData:public QueueItem{
    public:
        QueueItemData(T& item_data):_item_data(item_data){}
        const T& data(){
            return _item_data;
        }
        ~QueueItemData(){
        }
    private:
        QueueItemData(){}
        T _item_data;
    };
#if __cplusplus >= 201103L
    template <typename T>
    class QueueItemDataSharePtr:public QueueItem{
    public:
        QueueItemDataSharePtr(std::shared_ptr<T>& item_data):_item_data(item_data){}
        QueueItemDataSharePtr()= delete;
        const std::shared_ptr<T>& data(){
            return _item_data;
        }
        ~QueueItemDataSharePtr(){
        }
    private:
        std::shared_ptr<T> _item_data;
    };
#else
    template <typename T>
    class QueueItemDataSharePtr:public QueueItem{
    public:
        QueueItemDataSharePtr(zg_util::SharedPtr<T>& item_data):_item_data(item_data){}
        QueueItemDataSharePtr()= delete;
        const T& data(){
            return _item_data;
        }
        ~QueueItemDataSharePtr(){
        }
    private:
        zg_util::SharedPtr<T> &_item_data;
    };

#endif

    class Queue{
        struct WaitInfo{
            WaitInfo():pData(NULL){}
            Event ev;
            QueueItem* pData;
        };
    public:
        void Enqueue(QueueItem*);
        QueueItem* Dequeue();
        QueueItem* TryDequeue(int msec);
        QueueItem* dequeue_one();
        void Clear();
#if __cplusplus >= 201103L
        void ShrinkToFit();
#endif
        inline unsigned long size(){return _data_queue.size();}
        inline unsigned long wait_size(){return _wait_queue.size();}
    private:
        QueueItem* DequeueImpl(bool block= true,int wait_msec=0);
        deque<QueueItem*> _data_queue;
        deque<WaitInfo*> _wait_queue;
        Mutex _mutex;
    };
}

#endif
